﻿<script setup>
  const props = defineProps({
    menuList: { type: Array, default: () => [] },
    replaceFields: {
      type: Object,
      default: () => ({
        name: "categoryName",
        value: "id",
        children: "children",
        contents: "contents",
      }),
    },
  });
  const emit = defineEmits(["select"]);

  const menuRef = ref();
  const defaultActive = ref("");
  const defaultOpeneds = ref([]);
  const activeParentId = ref("");

  function hasChildren(node) {
    const k = props.replaceFields.children;
    return Array.isArray(node?.[k]) && node[k].length > 0;
  }
  function hasContents(node) {
    const k = props.replaceFields.contents;
    return Array.isArray(node?.[k]) && node[k].length > 0;
  }

  function getFirstPreferContentPath(list) {
    const { children, value } = props.replaceFields;
    if (!Array.isArray(list) || list.length === 0) return { node: null, openIds: [] };
    const path = [];
    let cur = list[0];
    path.push(cur);
    while (hasChildren(cur)) {
      const kids = cur[children];
      const next = kids.find(hasContents) || kids[0];
      cur = next;
      path.push(cur);
    }
    const node = [...path].reverse().find(hasContents) || path[path.length - 1];
    const openIds = path.slice(0, -1).map(n => String(n?.[value] ?? ""));
    return { node, openIds };
  }

  function findNodeById(list, id) {
    const { value, children } = props.replaceFields;
    const sid = String(id);
    const stack = Array.isArray(list) ? [...list] : [];
    while (stack.length) {
      const n = stack.shift();
      if (String(n?.[value]) === sid) return n;
      if (Array.isArray(n?.[children])) stack.push(...n[children]);
    }
    return null;
  }

  watch(
    () => props.menuList,
    async list => {
      const { node, openIds } = getFirstPreferContentPath(list || []);
      defaultOpeneds.value = openIds;
      activeParentId.value = "";
      defaultActive.value = node ? String(node[props.replaceFields.value]) : "";
      await nextTick();
      if (node) emit("select", node);
    },
    { immediate: true, deep: true }
  );

  function handleSelect(id) {
    activeParentId.value = "";
    const node = findNodeById(props.menuList, id);
    emit("select", node || { id });
  }

  function handleParentClick(id) {
    activeParentId.value = String(id);
    const node = findNodeById(props.menuList, id);
    emit("select", node || { id });
  }
</script>

<template>
  <div class="menutree-wrapper">
    <el-menu
      ref="menuRef"
      :default-active="defaultActive"
      :default-openeds="defaultOpeneds"
      text-color="#1B0204"
      active-text-color="#4753FF"
      unique-opened
      @select="handleSelect"
    >
      <!-- 一级 -->
      <template v-for="n0 in menuList" :key="n0[replaceFields.value]">
        <el-sub-menu
          v-if="n0[replaceFields.children]?.length"
          :index="String(n0[replaceFields.value])"
          class="menu-level-sub-1"
        >
          <template #title>
            <div class="submenu-title" @click="handleParentClick(n0[replaceFields.value])">
              <span
                class="node-label l1"
                :class="{ 'menu-title-active': activeParentId === String(n0[replaceFields.value]) }"
              >
                {{ n0[replaceFields.name] }}
              </span>
            </div>
          </template>

          <!-- 二级 -->
          <template v-for="n1 in n0[replaceFields.children]" :key="n1[replaceFields.value]">
            <el-sub-menu
              v-if="n1[replaceFields.children]?.length"
              :index="String(n1[replaceFields.value])"
              class="menu-level-sub-2"
            >
              <template #title>
                <div class="submenu-title" @click="handleParentClick(n1[replaceFields.value])">
                  <span
                    class="node-label l2"
                    :class="{ 'menu-title-active': activeParentId === String(n1[replaceFields.value]) }"
                  >
                    {{ n1[replaceFields.name] }}
                  </span>
                </div>
              </template>

              <!-- 三级（叶子） -->
              <el-menu-item
                v-for="n2 in n1[replaceFields.children]"
                :key="n2[replaceFields.value]"
                :index="String(n2[replaceFields.value])"
                class="menu-level-item-3"
              >
                <span class="node-label l3">{{ n2[replaceFields.name] || "" }}</span>
              </el-menu-item>
            </el-sub-menu>

            <!-- 二级本身就是叶子 -->
            <el-menu-item v-else :index="String(n1[replaceFields.value])" class="menu-level-item-2">
              <span class="node-label l2">{{ n1[replaceFields.name] || "" }}</span>
            </el-menu-item>
          </template>
        </el-sub-menu>

        <!-- 一级本身就是叶子 -->
        <el-menu-item v-else :index="String(n0[replaceFields.value])" class="menu-level-item-1">
          <span class="node-label l1">{{ n0[replaceFields.name] || "" }}</span>
        </el-menu-item>
      </template>
    </el-menu>
  </div>
</template>

<style lang="scss" scoped>
  .menutree-wrapper {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding: 12px;
    overflow-y: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .menutree-wrapper::-webkit-scrollbar {
    display: none;
  }

  /* 文本色统一 */
  :deep(.el-menu .el-menu-item),
  :deep(.el-menu .el-sub-menu .el-sub-menu__title span) {
    color: #15194d !important;
    font-family:
      PingFang SC,
      system-ui,
      -apple-system,
      "Segoe UI",
      Roboto,
      "Helvetica Neue",
      Arial !important;
  }

  /* 一级加粗 */
  :deep(.menu-level-item-1 > span),
  :deep(.menu-level-sub-1 > .el-sub-menu__title > span) {
    font-weight: bold !important;
  }

  /* 取消固定高度，启用自适应；并让箭头/文字垂直居中对齐 */
  :deep(.el-menu-item),
  :deep(.el-sub-menu__title) {
    height: auto !important;
    line-height: 22px !important;
    padding-top: 8px !important;
    padding-bottom: 8px !important;
    align-items: center !important; /* ★ 居中对齐，解决箭头与文字不齐 */
  }

  /* 多行时箭头保持居中，不要上移/下移 */
  :deep(.el-sub-menu__title .el-sub-menu__icon-arrow) {
    align-self: center !important;
    margin-top: 0 !important;
    transform: none; /* Element Plus 会在展开时旋转，这里不取消旋转，只清除额外偏移 */
  }

  /* 缩进与字号（保留你的视觉） */
  :deep(.menu-level-sub-1 > .el-sub-menu__title),
  :deep(.menu-level-item-1) {
    margin-top: 4px !important;
    padding-left: 12px !important;
  }
  :deep(.menu-level-sub-2 > .el-sub-menu__title),
  :deep(.menu-level-item-2) {
    margin-top: 4px !important;
    padding-left: 34px !important;
    font-size: 14px !important;
  }
  :deep(.menu-level-sub-3 > .el-sub-menu__title),
  :deep(.menu-level-item-3) {
    margin-top: 4px !important;
    padding-left: 48px !important;
    font-size: 14px !important;
  }

  /* 悬浮/选中样式 */
  :deep(.menu-level-item-1:hover),
  :deep(.menu-level-sub-1 > .el-sub-menu__title:hover),
  :deep(.menu-level-item-2:hover),
  :deep(.menu-level-sub-2 > .el-sub-menu__title:hover),
  :deep(.menu-level-item-3:hover),
  :deep(.menu-level-sub-3 > .el-sub-menu__title:hover) {
    background-color: #e5e6eb !important;
    border-radius: 8px !important;
  }
  :deep(.menu-level-item-1.is-active) {
    background-color: #f0f3ff !important;
    // color: var(--bd) !important;
    color: #5947f1 !important;
    font-weight: bold !important;
    border-radius: 8px !important;
  }
  :deep(.menu-level-item-2.is-active),
  :deep(.menu-level-item-3.is-active) {
    background-color: #f7f7f8 !important;
    // color: var(--bd) !important;
    color: #5947f1 !important;
    border-radius: 8px !important;
    font-weight: bold !important;
  }
  :deep(.menu-level-item-2.is-active:hover),
  :deep(.menu-level-item-3.is-active:hover) {
    background-color: #e5e6eb !important;
    border-radius: 8px !important;
  }
  :deep(.el-menu .el-menu--inline) {
    background-color: #f7f7f8 !important;
    border-radius: 8px !important;
  }
  :deep(.el-menu) {
    border-right: none !important;
  }

  /* 文本：允许换行显示完整，不再省略，不用 tooltip */
  .node-label {
    display: block;
    flex: 1 1 auto;
    white-space: normal !important;
    word-break: break-word; /* 若纯中文可用 break-all */
  }
  .node-label.l1 {
    font-weight: 600;
  }
  .submenu-title {
    display: block;
    width: 100%;
  }

  /* 标题用 flex：文本在左、箭头在最右 */
  :deep(.el-sub-menu__title) {
    display: flex !important;
    align-items: center !important; /* 垂直居中 */
    height: auto !important; /* 允许多行 */
    line-height: 22px !important;
    padding-top: 8px !important;
    padding-bottom: 8px !important;
    /* 右侧稍留内边距，防止贴边 */
    padding-right: 12px !important;
  }

  /* 文本容器占满左侧空间，允许换行 */
  .submenu-title {
    display: block;
    width: 100%;
    flex: 1 1 auto; /* ★ 关键：把剩余宽度都给文本 */
    min-width: 0; /* 避免和箭头抢行导致溢出 */
  }
  .node-label {
    display: block;
    white-space: normal !important;
    word-break: break-word;
  }

  /* 箭头加入 flex 流、推到最右侧并垂直居中 */
  :deep(.el-sub-menu__title .el-sub-menu__icon-arrow) {
    position: static !important; /* 不用绝对定位 */
    margin-left: auto !important; /* ★ 靠右 */
    flex: 0 0 auto !important;
    align-self: center !important; /* 垂直居中 */
    height: 20px;
    line-height: 20px;
    transform: rotate(0deg) !important; /* 取消默认位移/旋转 */
  }

  /* 展开时仍然旋转，但保持在最右且不下移 */
  :deep(.is-opened > .el-sub-menu__title .el-sub-menu__icon-arrow) {
    transform: rotate(180deg) !important;
  }
</style>
